/**
 * @file configweave.cpp
 * @brief ConfigWeave 外观类实现文件，完成流水线组装与运行
 * @details 实现对 provider/transformer/validator/sink 的增添，
 * 以及执行 `run` 获得只读根与错误集合。同时提供 `Result` 的便捷读取方法实现。
 */
#include "configweave.h"

namespace cfg
{

/**
 * @brief 结果是否无错误且存在有效根
 */
bool
ConfigWeave::Result::ok() const noexcept
{
    return root != nullptr && errors.empty();
}

/**
 * @brief 创建只读根视图
 * @return 若 `root` 为空则返回空视图（current=nullptr）
 */
View
ConfigWeave::Result::view() const
{
    return View(root);
}

/**
 * @brief 便捷读取整型配置
 * @param path 路径（支持 JSON Pointer 与 a.b[0].c 语法）
 * @return 成功返回值，失败返回 `unexpected(ConfigError)`
 */
expected<int64_t, ConfigError>
ConfigWeave::Result::get_int64(std::string_view path) const
{
    return view().lookup(path).and_then([](const View & v) { return v.get_int64(); });
}

/**
 * @brief 便捷读取数值配置
 * @param path 路径
 * @return 成功返回值，失败返回 `unexpected(ConfigError)`
 */
expected<double, ConfigError>
ConfigWeave::Result::get_number(std::string_view path) const
{
    return view().lookup(path).and_then([](const View & v) { return v.get_number(); });
}

/**
 * @brief 便捷读取字符串配置
 * @param path 路径
 * @return 成功返回值，失败返回 `unexpected(ConfigError)`
 */
expected<std::string, ConfigError>
ConfigWeave::Result::get_string(std::string_view path) const
{
    return view().lookup(path).and_then([](const View & v) { return v.get_string(); });
}

/**
 * @brief 便捷读取布尔配置
 * @param path 路径
 * @return 成功返回值，失败返回 `unexpected(ConfigError)`
 */
expected<bool, ConfigError>
ConfigWeave::Result::get_bool(std::string_view path) const
{
    return view().lookup(path).and_then([](const View & v) { return v.get_bool(); });
}

/**
 * @brief 添加单文件 provider（"single_file"），读取并合入
 * @param path 文件路径（支持 YAML/JSON）
 * @return 返回 `ConfigWeave&`，以支持链式调用
 */
ConfigWeave &
ConfigWeave::from_file(std::string path)
{
    ProviderSpec p;
    p.name = "single_file";
    p.options["path"] = std::move(path);
    _providers.emplace_back(std::move(p));
    return *this;
}

/**
 * @brief 添加键规整 transformer（"normalize_keys"）
 * @param style 规整风格（如 `lowercase`、`snake_case`）
 * @return 返回 `ConfigWeave&`
 */
ConfigWeave &
ConfigWeave::normalize_keys(std::string style)
{
    TransformerSpec t;
    t.name = "normalize_keys";
    t.options["style"] = std::move(style);
    _transformers.emplace_back(std::move(t));
    return *this;
}

/**
 * @brief 添加必填键 validator（"required_key"）
 * @param path 必填键路径
 * @return 返回 `ConfigWeave&`
 */
ConfigWeave &
ConfigWeave::require_key(std::string path)
{
    ValidatorSpec v;
    v.name = "required_key";
    v.options["path"] = std::move(path);
    _validators.emplace_back(std::move(v));
    return *this;
}

ConfigWeave &
ConfigWeave::number_in_range(std::string path,
                             std::optional<double> min,
                             std::optional<double> max,
                             std::optional<double> default_value)
{
    ValidatorSpec v;
    v.name = "number_in_range";
    v.options["path"] = std::move(path);
    if (min)
        v.options["min"] = std::to_string(*min);
    if (max)
        v.options["max"] = std::to_string(*max);
    if (default_value)
        v.options["default"] = std::to_string(*default_value);
    _validators.emplace_back(std::move(v));
    return *this;
}

ConfigWeave &
ConfigWeave::enum_in_set(std::string path,
                         std::vector<std::string> values,
                         std::optional<std::string> default_value)
{
    ValidatorSpec v;
    v.name = "enum_in_set";
    v.options["path"] = std::move(path);
    // 以逗号拼接传递
    std::string joined;
    for (size_t i = 0; i < values.size(); ++i)
    {
        if (i)
            joined += ",";
        joined += values[i];
    }
    v.options["values"] = std::move(joined);
    if (default_value)
        v.options["default"] = std::move(*default_value);
    _validators.emplace_back(std::move(v));
    return *this;
}

ConfigWeave &
ConfigWeave::array_length(std::string path,
                          std::optional<size_t> min_len,
                          std::optional<size_t> max_len)
{
    ValidatorSpec v;
    v.name = "array_length";
    v.options["path"] = std::move(path);
    if (min_len)
        v.options["min_len"] = std::to_string(*min_len);
    if (max_len)
        v.options["max_len"] = std::to_string(*max_len);
    _validators.emplace_back(std::move(v));
    return *this;
}

ConfigWeave &
ConfigWeave::object_required_keys(std::string path, std::vector<std::string> keys)
{
    ValidatorSpec v;
    v.name = "object_required_keys";
    v.options["path"] = std::move(path);
    std::string joined;
    for (size_t i = 0; i < keys.size(); ++i)
    {
        if (i)
            joined += ",";
        joined += keys[i];
    }
    v.options["keys"] = std::move(joined);
    _validators.emplace_back(std::move(v));
    return *this;
}

ConfigWeave &
ConfigWeave::exclusive_minimum(std::string path, double minimum)
{
    ValidatorSpec v;
    v.name = "exclusive_minimum";
    v.options["path"] = std::move(path);
    v.options["minimum"] = std::to_string(minimum);
    _validators.emplace_back(std::move(v));
    return *this;
}

ConfigWeave &
ConfigWeave::exclusive_maximum(std::string path, double maximum)
{
    ValidatorSpec v;
    v.name = "exclusive_maximum";
    v.options["path"] = std::move(path);
    v.options["maximum"] = std::to_string(maximum);
    _validators.emplace_back(std::move(v));
    return *this;
}

ConfigWeave &
ConfigWeave::unique_items(std::string path)
{
    ValidatorSpec v;
    v.name = "unique_items";
    v.options["path"] = std::move(path);
    _validators.emplace_back(std::move(v));
    return *this;
}

ConfigWeave &
ConfigWeave::contains(std::string path, std::string value)
{
    ValidatorSpec v;
    v.name = "contains";
    v.options["path"] = std::move(path);
    v.options["value"] = std::move(value);
    _validators.emplace_back(std::move(v));
    return *this;
}

ConfigWeave &
ConfigWeave::dependent_required(std::string path,
                                std::string key,
                                std::vector<std::string> requires)
{
    ValidatorSpec v;
    v.name = "dependent_required";
    v.options["path"] = std::move(path);
    v.options["key"] = std::move(key);
    std::string joined;
    for (size_t i = 0; i < requires.size(); ++i)
    {
        if (i)
            joined += ",";
        joined += requires[i];
    }
    v.options["requires"] = std::move(joined);
    _validators.emplace_back(std::move(v));
    return *this;
}

// 组合校验器便捷方法实现
static void
append_indexed_sub(ValidatorSpec & v, int idx, const ConfigWeave::SubValidator & s)
{
    std::string pfx = std::string("v") + std::to_string(idx);
    v.options[pfx + ".name"] = s.name;
    for (const auto & kv : s.options)
    {
        v.options[pfx + ".opt." + kv.first] = kv.second;
    }
}

static void
append_named_sub(ValidatorSpec & v, const std::string & name, const ConfigWeave::SubValidator & s)
{
    v.options[name + ".name"] = s.name;
    for (const auto & kv : s.options)
    {
        v.options[name + ".opt." + kv.first] = kv.second;
    }
}

ConfigWeave &
ConfigWeave::all_of(const std::vector<SubValidator> & subs)
{
    ValidatorSpec v;
    v.name = "all_of";
    int idx = 1;
    for (const auto & s : subs)
    {
        append_indexed_sub(v, idx++, s);
    }
    _validators.emplace_back(std::move(v));
    return *this;
}

ConfigWeave &
ConfigWeave::any_of(const std::vector<SubValidator> & subs)
{
    ValidatorSpec v;
    v.name = "any_of";
    int idx = 1;
    for (const auto & s : subs)
    {
        append_indexed_sub(v, idx++, s);
    }
    _validators.emplace_back(std::move(v));
    return *this;
}

ConfigWeave &
ConfigWeave::one_of(const std::vector<SubValidator> & subs)
{
    ValidatorSpec v;
    v.name = "one_of";
    int idx = 1;
    for (const auto & s : subs)
    {
        append_indexed_sub(v, idx++, s);
    }
    _validators.emplace_back(std::move(v));
    return *this;
}

ConfigWeave &
ConfigWeave::not_(const SubValidator & sub)
{
    ValidatorSpec v;
    v.name = "not";
    append_named_sub(v, "not", sub);
    _validators.emplace_back(std::move(v));
    return *this;
}

ConfigWeave &
ConfigWeave::if_then_else(const SubValidator & if_sub,
                          std::optional<SubValidator> then_sub,
                          std::optional<SubValidator> else_sub)
{
    ValidatorSpec v;
    v.name = "if_then_else";
    append_named_sub(v, "if", if_sub);
    if (then_sub)
        append_named_sub(v, "then", *then_sub);
    if (else_sub)
        append_named_sub(v, "else", *else_sub);
    _validators.emplace_back(std::move(v));
    return *this;
}

/**
 * @brief 添加任意 transformer（扩展点）
 * @param name 插件名称
 * @param options 插件选项
 * @return 返回 `ConfigWeave&`
 */
ConfigWeave &
ConfigWeave::add_transformer(std::string name, PluginOptions options)
{
    TransformerSpec t;
    t.name = std::move(name);
    t.options = std::move(options);
    _transformers.emplace_back(std::move(t));
    return *this;
}

/**
 * @brief 添加任意 validator（扩展点）
 * @param name 插件名称
 * @param options 插件选项
 * @return 返回 `ConfigWeave&`
 */
ConfigWeave &
ConfigWeave::add_validator(std::string name, PluginOptions options)
{
    ValidatorSpec v;
    v.name = std::move(name);
    v.options = std::move(options);
    _validators.emplace_back(std::move(v));
    return *this;
}

/**
 * @brief 添加一个 sink（如写文件/打印）
 * @param name sink 插件名称
 * @param options sink 所需的选项键值
 * @return 引用自身以便链式调用
 */
ConfigWeave &
ConfigWeave::add_sink(std::string name, PluginOptions options)
{
    SinkSpec s;
    s.name = std::move(name);
    s.options = std::move(options);
    _sinks.emplace_back(std::move(s));
    return *this;
}

/**
 * @brief 运行流水线
 * @return 结果快照，包含只读根与错误集合
 */
ConfigWeave::Result
ConfigWeave::run() const
{
    PipelineSpec spec;
    spec.providers = _providers;
    spec.transformers = _transformers;
    spec.validators = _validators;
    spec.sinks = _sinks;

    // 合并全局分散式附加的 transformers/validators
    {
        auto extra_t = AttachmentRegistry::instance().collect_transformers();
        auto extra_v = AttachmentRegistry::instance().collect_validators();
        spec.transformers.insert(spec.transformers.end(), extra_t.begin(), extra_t.end());
        spec.validators.insert(spec.validators.end(), extra_v.begin(), extra_v.end());
    }

    PipelineRunner runner;
    PipelineResult r = runner.run(spec);

    Result out;
    out.root = std::move(r.root);
    out.errors = std::move(r.errors);
    return out;
}

} // namespace cfg
